import Vue from 'vue/dist/vue.esm'

const CLS = 'batch-selecting'
Vue.directive('batch-area', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted: (el, binding) => {
        // 设置被绑定元素el（即上述的box）的position为relative，目的是让蓝色半透明遮罩area相对其定位
        const relSelName = binding.value.relSelector
        if (relSelName) {
            el.querySelector(relSelName).style.position = 'relative';
        } else {
            el.style.position = 'relative';
        }
        // console.log(el)
        // 记录el在视窗中的位置elPos
        const { x, y } = el.getBoundingClientRect()
        const elPos = { x, y }
        // 获取该指令调用者传递过来的参数：className
        // v-batch-select="{ className: '.el-checkbox', selectIdxs }"
        // 表示要使用鼠标框选类名为'.el-checkbox'的元素
        const optionClassName = binding.value.selector
        let options = []
        // 获取被框选对象们的x、y、width、height
        let optionsXYWH = []

        const getScrollY = binding.value.getScrollY

        // 创建一个div作为area区域，注意定位是absolute，visibility初始值是hidden
        let cachedArea = {
            style: {}
        }
        const area = document.createElement('div')
        // border: 1px solid #409eff; background-color: rgba(64, 158, 255, 0.1);
        area.style = 'position: absolute; z-index: 10; visibility: hidden;'
        area.className = 'batch-select-area'
        area.innerHTML = ''
        el.appendChild(area)
        // const area2 = document.createElement('div')
        // // border: 1px solid #409eff; background-color: rgba(64, 158, 255, 0.1);
        // area2.style = 'position: absolute; z-index: 10; visibility: hidden;'
        // area2.className = 'batch-select-area'
        // area2.innerHTML = ''
        // el.appendChild(area2)
        el.onmousedown = (e) => {
            if (!e.shiftKey) {
                // console.log('sdsdsds', e)
                return;
            }
            el.classList.add(CLS)
            options = [].slice.call(el.querySelectorAll(optionClassName))
            options.forEach(v => {
                const obj = v.getBoundingClientRect()
                optionsXYWH.push({
                    x: obj.x - elPos.x,
                    y: obj.y - elPos.y + getScrollY(),
                    w: obj.width,
                    h: obj.height,
                    obj: v
                })
            })
            // console.log(optionsXYWH)
            // 获取鼠标按下时相对box的坐标
            const startX = e.clientX - elPos.x
            const startY = e.clientY - elPos.y + getScrollY()
            // 判断鼠标按下后是否发生移动的标识
            let hasMove = false
            document.onmousemove = (e) => {
                hasMove = true
                // 显示area
                area.style.visibility = 'visible'
                // 获取鼠标移动过程中指针的实时位置
                const endX = e.clientX - elPos.x
                const endY = e.clientY - elPos.y  + getScrollY()
                // 这里使用绝对值是为了兼容鼠标从各个方向框选的情况
                const width = Math.abs(endX - startX)
                const height = Math.abs(endY - startY)
                // 根据初始位置和实时位置计算出area的left、top、width、height
                const left = Math.min(startX, endX)
                const top = Math.min(startY, endY)
                // 实时绘制
                cachedArea.style.left = `${left}px`
                cachedArea.style.top = `${top}px`
                cachedArea.style.width = `${width}px`
                cachedArea.style.height = `${height}px`
                if (binding?.value?.onMouseMove) {

                    let selectIdxs = []
                    let doms = []
                    // const { left, top, width, height } = cachedArea.style
                    const areaTop = parseInt(top)
                    const areaRight = parseInt(left) + parseInt(width)
                    const areaBottom = parseInt(top) + parseInt(height)
                    const areaLeft = parseInt(left)
                    optionsXYWH.forEach((v, i) => {
                        const optionTop = v.y
                        const optionRight = v.x + v.w
                        const optionBottom = v.y + v.h
                        const optionLeft = v.x
                        if (!(areaTop > optionBottom || areaRight < optionLeft || areaBottom < optionTop || areaLeft > optionRight)) {
                            // 该指令的调用者可以监听到selectIdxs的变化
                            // console.log(v.obj)
                            // let dom  = v.obj.querySelector('[batch-select-dataset]')
                            selectIdxs.push(v.obj.dataset)
                            doms.push(v.obj)
                        }
                    })

                    binding?.value?.onMouseMove(selectIdxs, doms, area)
                }
            }
            document.onmouseup = (e) => {
                el.classList.remove(CLS)
                document.onmousemove = document.onmouseup = null
                if (hasMove) {
                    // 鼠标抬起时，如果之前发生过移动，则执行碰撞检测
                    const { left, top, width, height } = cachedArea.style
                    const areaTop = parseInt(top)
                    const areaRight = parseInt(left) + parseInt(width)
                    const areaBottom = parseInt(top) + parseInt(height)
                    const areaLeft = parseInt(left)
                    binding.value.selectIdxs.length = 0
                    optionsXYWH.forEach((v, i) => {
                        const optionTop = v.y
                        const optionRight = v.x + v.w
                        const optionBottom = v.y + v.h
                        const optionLeft = v.x
                        if (!(areaTop > optionBottom || areaRight < optionLeft || areaBottom < optionTop || areaLeft > optionRight)) {
                            // 该指令的调用者可以监听到selectIdxs的变化
                            // console.log(v.obj)
                            // let dom  = v.obj.querySelector('[batch-select-dataset]')
                            binding.value.selectIdxs.push({
                                // dataset: dom?.dataset,
                                // content: dom?.value,
                                dataset: v.obj.dataset,
                                index: i
                            })
                        }
                    })
                }
                // 恢复以下数据
                hasMove = false
                area.style.visibility = 'hidden'
                area.style.left = 0
                area.style.top = 0
                area.style.width = 0
                area.style.height = 0
                // 清除代码
                optionsXYWH = []
                return false
            }
        }
    }
})
